package app.species;

import sim.engine.*;
import sim.util.*;
import java.io.*;

import app.species.ANN.*;

public class BestCreatureDisplayer implements Steppable {

	static final long serialVersionUID = 1L;
	private final static boolean ENABLE_LOGGING = false; 
	private static PrintWriter pr;

	public BestCreatureDisplayer(int runNum) {

		if(ENABLE_LOGGING){
		try {
			pr = new PrintWriter(new BufferedWriter(new FileWriter(
					"output/run" + runNum + "complexity.out")));
		} catch (IOException e) {
			e.printStackTrace();
		}
		}

	}

	public void step(SimState state) {

		SpeciesSim sim = (SpeciesSim) state;
		Bag bestMovingFoodBag = new Bag();
		Bag bestStationaryFoodBag = new Bag();
		Bag bagOfCreatures = sim.creatures.getAllObjects();
		Bag bagOfSpecies = new Bag();
		Bag creaturesInSpeciesBag, newSpeciesBag;
		int maxMovingFoodEaten, maxStationaryFoodEaten;
		Creature creature, randomCreature;
		boolean creatureInExistingSpecies;
		boolean updateSpecies = sim.schedule.getSteps() % 100 == 0;

		maxMovingFoodEaten = maxStationaryFoodEaten = Integer.MIN_VALUE;

		for (int i = 0; i < bagOfCreatures.numObjs; i++) {

			creature = (Creature) bagOfCreatures.objs[i];

			
			if (ENABLE_LOGGING && sim.schedule.getSteps() % 500 == 0 && pr != null) {
				pr.println(sim.schedule.getSteps() + " "
						+ creature.brain.getSomaChromeLen() + " "
						+ creature.brain.getAxonChromeLen());
			}

			if (sim.schedule.getSteps() % 10 == 0) {
				creature.isBestMovingFoodEater = false;
				creature.isBestStationaryFoodEater = false;

				if (creature.getMovingFoodEaten() == maxMovingFoodEaten) {
					bestMovingFoodBag.add(creature);
				} else if (creature.getMovingFoodEaten() > maxMovingFoodEaten) {
					bestMovingFoodBag.clear();
					bestMovingFoodBag.add(creature);
					maxMovingFoodEaten = creature.getMovingFoodEaten();
				}

				if (creature.getStationaryFoodEaten() == maxStationaryFoodEaten) {
					bestStationaryFoodBag.add(creature);
				} else if (creature.getStationaryFoodEaten() > maxStationaryFoodEaten) {
					bestStationaryFoodBag.clear();
					bestStationaryFoodBag.add(creature);
					maxStationaryFoodEaten = creature.getStationaryFoodEaten();
				}
			}
			if (updateSpecies) {

				// check out which species this creature is in
				creatureInExistingSpecies = false;
				for (int j = 0; j < bagOfSpecies.numObjs; j++) {

					creaturesInSpeciesBag = (Bag) bagOfSpecies.objs[j];

					randomCreature = (Creature) creaturesInSpeciesBag.objs[0];

					if (creature.brain.isCompatible(randomCreature.brain)) {
						creatureInExistingSpecies = true;
						creaturesInSpeciesBag.add(creature);
						creature.setSpeciesNum(randomCreature.getSpeciesNum());
						break;
					}

				}

				// creature is not in existing species, so create a new species
				if (!creatureInExistingSpecies) {
					creature.setSpeciesNum(bagOfSpecies.numObjs);
					newSpeciesBag = new Bag();
					newSpeciesBag.add(creature);
					bagOfSpecies.add(newSpeciesBag);

				}

			}

		}

		if (updateSpecies) {

			sim.numSpecies = bagOfSpecies.numObjs;
			/*
			 * if(sim.schedule.getSteps() % 1000 == 0){
			 * 
			 * System.out.println("Time step: " + sim.schedule.getSteps());
			 * System.out.println("Num creatures: " + bagOfCreatures.numObjs);
			 * System.out.println("Num species: " + sim.numSpecies);
			 * System.out.println("Compatibility threshold: " +
			 * Brain.compThreshold);
			 * 
			 * for(int i = 0; i < bagOfSpecies.numObjs; i++){ Bag tmp =
			 * (Bag)bagOfSpecies.objs[i]; System.out.println("Species " + i +
			 * ": " + tmp.numObjs); }
			 * 
			 * System.out.println();
			 * 
			 * }
			 */
			// update the number compatibility threshold
			if (sim.numSpecies < 10) {
				Brain.addToCompThreshold(-0.01);
			} else if (sim.numSpecies > 20) {
				Brain.addToCompThreshold(0.01);
			}

		}

		for (int i = 0; i < bestMovingFoodBag.numObjs; i++) {
			creature = (Creature) bestMovingFoodBag.objs[i];
			creature.isBestMovingFoodEater = true;
		}

		for (int i = 0; i < bestStationaryFoodBag.numObjs; i++) {
			creature = (Creature) bestStationaryFoodBag.objs[i];
			creature.isBestStationaryFoodEater = true;
		}

	}

	public void closeFile() {
		if(ENABLE_LOGGING && this.pr != null)this.pr.close();
	}
}
